package org.kitten.core.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kitten.core.C;

public class FileUtil {
    private static final Log logger = LogFactory.getLog(FileUtil.class);

	public static URL getURL(File f) {
		try {
			return f.toURI().toURL();
		} catch (MalformedURLException e) {
			logger.error(ErrorUtil.getError(e));
		}
		return null;
	}

	/**
	 * 把文件filename转化为byte[]并返回
	 * 
	 * 
	 * 示例：byte[] pic = FileUtil.getBytes("C:\\test.jpg");
	 */
	public static byte[] getBytes(String filename) {
		FileInputStream fis = null;
		try {
			File f = new File(filename);
			fis = new FileInputStream(f);
			byte[] b = new byte[(int) f.length()];
			fis.read(b);
			fis.close();
			return b;
		} catch (Exception ex) {
			logger.error(ErrorUtil.getError(ex));
			return null;
		} finally {
			close(fis);
		}
	}

	/**
	 * 把字节数组byte[] 写入文件 filename, 和getBytes()方法正好相反
	 */
	public static void bytesToFile(byte[] b, String filename) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(filename);
			fos.write(b);
		} catch (Exception ex) {
			logger.error(ErrorUtil.getError(ex));
		} finally {
			close(fos);
		}
	}

	// --------- transfer stream ----------------------
	/**
	 * 以下的所有transfer(a,b)方法，就是把a写到b
	 */
	public static void transfer(String str, Writer w) {
		try {
			w.write(str);
			w.flush();
		} catch (Exception ex) {
			logger.error(ErrorUtil.getError(ex));
		} finally {
			close(w);
		}
	}

	public static void transfer(byte[] in, OutputStream out) {
		try {
			out.write(in);
		} catch (Exception ex) {
			logger.error(ErrorUtil.getError(ex));
		} finally {
			close(out);
		}
	}

	public static void tranfer(InputStream in, OutputStream out) {
		tranfer(in, out, 102400);
	}

	public static void tranfer(InputStream in, OutputStream out, int buffSize) {

		try {
			byte[] buf = new byte[buffSize];
			int len;
			while ((len = in.read(buf)) != -1) {
				out.write(buf, 0, len);
			}
		} catch (Exception ex) {
			logger.error(ErrorUtil.getError(ex));
		} finally {
			close(out, in);
		}
	}

	public static String getFileContent(File f, String lineBreak,
			String encoding) throws Exception {
		FileInputStream fr = null;
		BufferedReader br = null;
		StringBuffer source = new StringBuffer((int) f.length());
		if (f.length() > 0) {
			try {
				fr = new FileInputStream(f);
				if (encoding != null && !encoding.equals("")) {
					br = new BufferedReader(new InputStreamReader(fr, encoding));
				} else {
					br = new BufferedReader(new InputStreamReader(fr));
				}
				String tempStr = "";
				while ((tempStr = br.readLine()) != null) {
					source.append(tempStr);
					source.append(lineBreak);
				}
				source.setLength(source.length() - lineBreak.length());
			} catch (Exception e) {
				throw e;
			} finally {
				close(fr);
				close(br);
			}
		}
		return source.toString();
	}

	public static String getFileContent(InputStream is, String lineBreak,
			String encoding) throws Exception {
		BufferedReader br = null;
		StringBuffer source = new StringBuffer();
		try {
			if (encoding != null && !encoding.equals("")) {
				br = new BufferedReader(new InputStreamReader(is, encoding));
			} else {
				br = new BufferedReader(new InputStreamReader(is));
			}
			String tempStr = "";
			while ((tempStr = br.readLine()) != null) {
				source.append(tempStr);
				source.append(lineBreak);
			}
			source.setLength(source.length() - lineBreak.length());
		} catch (Exception e) {
			throw e;
		} finally {
			close(is);
			close(br);
		}
		return source.toString();
	}

	public static String getFileContent(File f, String encoding)
			throws Exception {
		return getFileContent(f, C.LS, encoding);
	}

	public static String getFileContent(InputStream is, String encoding)
			throws Exception {
		return getFileContent(is, C.LS, encoding);
	}

	public static void setFileContent(File f, String content, String encoding)
			throws Exception {
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(f);
			byte[] buffer;
			if (encoding != null && !encoding.equals("")) {
				buffer = content.getBytes(encoding);
			} else {
				buffer = content.getBytes();
			}
			os.write(buffer, 0, buffer.length);
		} catch (Exception ex) {
			throw ex;
		} finally {
			close(os);
		}
	}

	/**
	 * 统计文件行数
	 * 
	 * @param filePath
	 * @return
	 */
	public static int getLineCount(String filePath) {

		logger.info("正在统计文件行数:" + filePath);
		File f = new File(filePath);
		FileReader fr = null;
		LineNumberReader br = null;
		int count = 0;
		try {
			fr = new FileReader(f);
			br = new LineNumberReader(fr);
			while (br.readLine() != null) {
				count++;
			}
		} catch (Exception e) {
			logger.error("统计文件行数出错:" + ErrorUtil.getError(e));
		} finally {
			FileUtil.close(br);
			FileUtil.close(fr);
		}
		return count;
	}

	public static void appendAtTheBeginning(File f, String content,
			String encoding) throws Exception {
		String origin = getFileContent(f, encoding);
		origin = content + origin;
		setFileContent(f, origin, encoding);
	}

	public static void appendAtTheEnd(File f, String content, String encoding)
			throws Exception {
		String origin = getFileContent(f, encoding);
		origin = origin + content;
		setFileContent(f, origin, encoding);
	}

	/**
	 * 得到文件的路径（不包括名字） 示例： FileUtil.getPath("c:\\a\\b\\c.txt") 返回 c:\a\b\
	 */
	public static String getPath(String source) {
		int pos1 = source.lastIndexOf("/");
		int pos2 = source.lastIndexOf("\\");
		int pos = pos1 > pos2 ? pos1 : pos2;
		return source.substring(0, pos + 1);
	}

	// ----------- close stream ----------------------
	/**
	 * 与文件相关的流，都可以调用FileHelper.close(..)来把它们关闭
	 */
	public static void close(Reader reader) {
		if (reader != null) {
			try {
				reader.close();
				reader = null;
			} catch (Exception e) {
				logger.error(ErrorUtil.getError(e));
			}
		}
	}

	public static void close(Writer w) {
		if (w != null) {
			try {
				w.close();
				w = null;
			} catch (Exception ex) {
				logger.error(ErrorUtil.getError(ex));
			}
		}
	}

	public static void close(InputStream in) {
		close(in, null);
	}

	public static void close(OutputStream out) {
		close(null, out);
	}

	public static void close(InputStream is, OutputStream os) {
		if (is != null) {
			try {
				is.close();
			} catch (IOException e) {
				logger.error(ErrorUtil.getError(e));
			}
			is = null;
		}
		if (os != null) {
			try {
				os.close();
			} catch (IOException e) {
				logger.error(ErrorUtil.getError(e));
			}
			os = null;
		}

	}

	public static void close(OutputStream os, InputStream is) {
		if (os != null) {
			try {
				os.close();
			} catch (IOException e) {
				logger.error(ErrorUtil.getError(e));
			}
			os = null;
		}
		if (is != null) {
			try {
				is.close();
			} catch (IOException e) {
				logger.error(ErrorUtil.getError(e));
			}
			is = null;
		}
	}

	/**
	 * 取得类路径下的文件流
	 * 
	 * @param packageName
	 *            包名,可以为空或null
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static InputStream getClasspathFile(final String fileName) {
		InputStream is = ClassUtil.getDefaultClassLoader().getResourceAsStream(
				fileName);
		if (is == null) {
			logger.error("getClasspathFile error: inputstream is null <"
					+ fileName + "> ");
		}
		return is;
	}

	public static InputStream getClasspathFile(String packageName,
			final String fileName) {
		if (packageName != null && !"".equals(packageName)) {
			String path = packageName.replaceAll("\\.", "/");
			path = path + "/" + fileName;
			return ClassUtil.getDefaultClassLoader().getResourceAsStream(
					fileName);
		} else {
			return ClassUtil.getDefaultClassLoader().getResourceAsStream(
					fileName);
		}
	}
}
